#pragma once
#include "base/function.h"
#include "util/mutex.h"
#include "util/noncopyable.h"
#include "base/timeeverymap.h"
#include "base/timeeventset.h"
#include "base/config.h"

#include <vector>
#include <string>
#include <atomic>

#include <pthread.h>
#include <sys/eventfd.h>
namespace net_tools
{

  namespace base
  {
    class Channel;
    class Connectpool;
    class Epoll;
    class Timeevent;
    class Timeevery;
    class Timequeue;
  } // namespace base

  namespace net
  {
    class Connectpool;
  } // namespace net
  class Eventloop : util::noncopyable
  {
  public:
    Eventloop(int size = _C::CHANNEL_DEFAULT_SIZE, int tid = 0);
    ~Eventloop();
    void Loop();
    //need run in right thread
    base::Channel *Get_free_channel(int fd);
    //already run in right thread
    void Free_channel(base::Channel *channel);
    //need run in right thread
    void Free_channel_right_now(base::Channel *channel);
    //already run in right thread
    void Addevent_right(base::Channel *channel);
    //already run in right thread
    void Modevent_right(base::Channel *channel);
    //already run in right thread
    void Delevent_right(base::Channel *channel);
    //need run in right thread
    void Addevent(base::Channel *channel);
    //need run in right thread
    void Modevent(base::Channel *channel);
    //need run in right thread
    void Delevent(base::Channel *channel);
    //判断了是否在正确线程
    void Run_in_right_thread(func func_);
    //不判断是否在正确线程，直接添加
    void Run_in_thread(func func_);
    //already run in right thread
    base::Timeevent *Run_after(func func_, timeval begin_time, base::Timeeventset *timeeventset = nullptr);
    //already run in right thread
    base::Timeevent *Run_at(func func_, timeval begin_time, base::Timeeventset *timeeventset = nullptr);
    //already run in right thread
    // 不要对io线程的eventloop本体多线程添加重名任务 如果添加的任务重名则会出现奇怪的bug
    base::Timeevery *Run_every(func func_, timeval begin_time, timeval time, int count, const std::string &job_name, base::Timeeverymap *timeeverymap = nullptr);
    //already run in right thread
    void Deltimejob_every(const std::string job_name);
    //need in right thread
    bool Deltimejob_once(base::Timeevent *timeevent);

    void Init_thread_id();
    bool Is_in_right_thread();
    std::string *Get_Thread_name();
    //for Tcp server
    net::Connectpool *connectpool_;

  private:
    void Wakeup_job();
    void Wakeup_by_other();
    void Wakeup();
    unsigned int thread_tid;

    // 没有同步语义设置 仅x86平台可用
    std::atomic<bool> wakeup_;
    base::Epoll *epoll_;
    base::Timequeue *timequeue_;
    int wakeupfd_;
    bool quit;
    eventfd_t wakeup_event_use_;
    util::Mutex mutex_;
    std::vector<func> wakeup_job_;
    base::Timeeverymap timeeverymap_;
    base::Timeeventset timeeventset_;
  };

} // namespace net_tools